package com.ocp.macro.filter;

import com.ocp.macro.entity.Payload;
import com.ocp.macro.entity.UserInfoToken;
import com.ocp.macro.enums.DataCode;
import com.ocp.macro.utils.JwtUtil;
import com.ocp.macro.utils.ResultInfoUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

@Slf4j
public class JwtVerifyFilter extends BasicAuthenticationFilter {
    private RedisTemplate<String, Object> redisTemplate;

    public JwtVerifyFilter(AuthenticationManager authenticationManager, RedisTemplate<String, Object> redisTemplate){
        super(authenticationManager);
        this.redisTemplate = redisTemplate;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
        log.debug("认证权限过滤链：{}",request.getRequestURL().toString());

        String header = request.getHeader("Authorization");

        if (header==null){// 没有进行登录
            errorRequest(response);
            return;
        }


        //获取用户请求中的token中获取用户信息
        String[] authInfo = header.split(":");

        if (authInfo.length!=2){ // 错误身份
            errorRequest(response);
        }

        String token = authInfo[1]; // 客户端token信息
        String privateKey = JwtUtil.getPrivateKey(request); // 获取密钥
        String redisKey = authInfo[0]+"::"+ privateKey; // 获取redis服务器中的token的key

        if (request.getRequestURI().equals("/macro/logout")){// 登出
            redisTemplate.delete(redisKey);
            Map<String, Object> data = new HashMap<>();
            data.put("code", DataCode.SUCCESS.getCode());
            data.put("message", DataCode.SUCCESS.getMessage());
            ResultInfoUtils.responseData(response, data);
            return;
        }


        String redisToken = (String) redisTemplate.opsForValue().get(redisKey);//获取redis中的token

        // 没有进行登录
        if(token == null || !token.equals(redisToken)){
            errorRequest(response);
            return;
        }


        Payload<UserInfoToken> payload = JwtUtil.getInfoFromToken(privateKey, token, UserInfoToken.class);
        if (payload==null){ // token内容可能被修改，或者token过期
            Map<String, Object> data = new HashMap<>();
            data.put("code", DataCode.TOKEN_ERROR_EXPIRE.getCode());
            data.put("message", DataCode.TOKEN_ERROR_EXPIRE.getMessage());
            ResultInfoUtils.responseData(response, data);
            redisTemplate.delete(redisKey);
            return;
        }

        UserInfoToken userToken = payload.getUserInfo();
        Authentication authResult = new UsernamePasswordAuthenticationToken
                (userToken,null,userToken.getAuthorities());
        // 添加认证信息
        SecurityContextHolder.getContext().setAuthentication(authResult);

        // 进行下一个过滤链
        chain.doFilter(request, response);
    }


    private void errorRequest(HttpServletResponse response) throws IOException {
        Map<String, Object> data = new HashMap<>();
        data.put("code", DataCode.NO_LOGIN.getCode());
        data.put("message", DataCode.NO_LOGIN.getMessage());
        ResultInfoUtils.responseData(response, data);
    }

}
